package pers.twf.twfRpc.protocol;

import io.vertx.core.buffer.Buffer;
import pers.twf.twfRpc.model.RpcRequest;
import pers.twf.twfRpc.model.RpcResponse;
import pers.twf.twfRpc.serializer.Serializer;
import pers.twf.twfRpc.serializer.SerializerFactory;

import java.io.IOException;

/**
 * 消息解码器
 */
public class ProtocolMessageDecoder {
    /**
     * 解码
     */
    public static ProtocolMessage<?> decode(Buffer buffer) throws IOException {
        ProtocolMessage.Header header = new ProtocolMessage.Header();
        byte magic = buffer.getByte(0);
        if (magic!= ProtocolConstant.PROTOCOL_MAGIC) {
            throw new RuntimeException("非法的magis消息");
        }
        header.setMagic(magic);
        header.setVersion(buffer.getByte(1));
        header.setSerializer(buffer.getByte(2));
        header.setType(buffer.getByte(3));
        header.setStatus(buffer.getByte(4));
        header.setRequestId(buffer.getLong(5));
        header.setBodyLength(buffer.getInt(13));
//        粘包问题的解决,读取指定长度的数据
        byte[] bodyBytes = buffer.getBytes(ProtocolConstant.MESSAGE_HEADER_LENGTH, ProtocolConstant.MESSAGE_HEADER_LENGTH + header.getBodyLength());


        ProtocolMessageSerializerEnum enumBySerializer = ProtocolMessageSerializerEnum.getEnumBySerializer(header.getSerializer());
        if (enumBySerializer==null) {
            throw new RuntimeException("serializer not exist");
        }
        Serializer serializer = SerializerFactory.getInstance(enumBySerializer.getName());
        ProtocolMessageTypeEnum enumByType = ProtocolMessageTypeEnum.getEnumByType(header.getType());
        if (enumByType==null) {
            throw new RuntimeException("type not exist");
        }
        switch (enumByType){
            case REQUEST:
                RpcRequest request = serializer.deserialize(bodyBytes, RpcRequest.class);
                return new ProtocolMessage<>(header,request);
            case RESPONSE:
                RpcResponse response = serializer.deserialize(bodyBytes, RpcResponse.class);
                return new ProtocolMessage<>(header,response);
            case HEART_BEAT:
            case OTHERS:
            default:
                throw new RuntimeException("type not support");
        }
    }
}
